package com.microservice.core.utils;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.List;
import java.util.function.BiConsumer;


/**
 * mybatis批处理工具
 *
 * @author hulei
 */
@Component
public class BatchInsertUtil {

    private final SqlSessionFactory sqlSessionFactory = SpringUtils.getBean(SqlSessionFactory.class);

    private static final Logger logger = LoggerFactory.getLogger(BatchInsertUtil.class);


    private int validateAndReturnBatchSize(Integer batchSize) {
        if (batchSize == null || batchSize <= 0) {
            throw new IllegalArgumentException("批处理条数必须大于0");
        }
        return batchSize;
    }

    public <T, U> int batchUpdateOrInsert(Integer batchSize,List<T> data, Class<U> mapperClass, BiConsumer<T, U> consumer) {
        int handleCount = validateAndReturnBatchSize(batchSize);
        int processedCount = 0;
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            for (T element : data) {
                consumer.accept(element, mapper);
                processedCount++;
                if (processedCount % handleCount == 0) {
                    batchSqlSession.flushStatements();
                }
            }
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            logger.error("批处理发生异常：{}", e.getMessage(), e);
            batchSqlSession.rollback();
            throw new RuntimeException("批量处理失败", e);
        } finally {
            batchSqlSession.close();
        }
        return processedCount;
    }
}

